﻿bob.ns.setNs('bob.prop.tests', {

    TestProp: function () {

        this.test_Property = function () {

            //read-write
            var value = undefined;
            var p = new bob.prop.Property(value);
            bob.assert.equals(value, p.get_value());
            value = 1;
            p.set_value(value);
            bob.assert.equals(value, p.get_value());
            value = undefined;
            p.set_value(value);
            bob.assert.equals(value, p.get_value());

            //read-only
            value = 1;
            p = new bob.prop.Property(value, true);
            var setter = p.get_setter();
            bob.assert.equals(value, p.get_value());
            bob.assert.isUndefined(p.set_value);
            bob.assert.isUndefined(p.get_setter);

            value = 2;
            setter(value);
            bob.assert.equals(value, p.get_value());
            bob.assert.isUndefined(p.set_value);
            bob.assert.isUndefined(p.get_setter);

            //write-only
            value = 1;
            p = new bob.prop.Property(value, false, true);
            var getter = p.get_getter();
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(p.get_value);
            bob.assert.isUndefined(p.get_getter);

            value = 2;
            p.set_value(value);
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(p.get_value);
            bob.assert.isUndefined(p.get_getter);
        };

        this.test_namedProp = function () {

            //read-write
            var obj = {};
            var value = 20;
            bob.prop.namedProp(obj, 'age', value);
            bob.assert.equals(value, obj.get_age());
            value = 21;
            obj.set_age(value);
            bob.assert.equals(value, obj.get_age());

            //read-only
            obj = {};
            value = 'Tengiz';
            var setter = bob.prop.namedProp(obj, 'name', value, true);
            bob.assert.equals(value, obj.get_name());
            bob.assert.isUndefined(obj.set_name);
            value += ' Tutisani';
            setter(value);
            bob.assert.equals(value, obj.get_name());
            bob.assert.isUndefined(obj.set_name);

            //write-only
            obj = {};
            value = 'Tengiz';
            var getter = bob.prop.namedProp(obj, 'name', value, false, true);
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(obj.get_name);
            value += ' Tutisani';
            obj.set_name(value);
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(obj.get_name);
        };

        this.test_namedPropWithPropObj = function () {

            //read-write
            var obj = {};
            var value = 20;
            var propObj = new bob.prop.Property(value);
            bob.prop.namedProp(true, obj, 'age', propObj);
            bob.assert.equals(value, obj.get_age());
            value = 21;
            obj.set_age(value);
            bob.assert.equals(value, obj.get_age());

            //read-only
            obj = {};
            value = 'Tengiz';
            var propObj = new bob.prop.Property(value, true);
            var setter = bob.prop.namedProp(true, obj, 'name', propObj);
            bob.assert.equals(value, obj.get_name());
            bob.assert.isUndefined(obj.set_name);
            value += ' Tutisani';
            setter(value);
            bob.assert.equals(value, obj.get_name());
            bob.assert.isUndefined(obj.set_name);

            //write-only
            obj = {};
            value = 'Tengiz';
            var propObj = new bob.prop.Property(value, false, true);
            var getter = bob.prop.namedProp(true, obj, 'name', propObj);
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(obj.get_name);
            value += ' Tutisani';
            obj.set_name(value);
            bob.assert.equals(value, getter());
            bob.assert.isUndefined(obj.get_name);
        };

        this.test_propFunction = function () {

            //read-write
            var value = 20;
            var prop = new bob.prop.Property(value);
            var fn = bob.prop.propFunction(true, prop);
            var fnNoError = bob.prop.propFunction(true, prop, true);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value = 21;
            fn(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //read-only
            value = 'Tengiz';
            prop = new bob.prop.Property(value, true);
            var setter = prop.get_setter();
            fn = bob.prop.propFunction(true, prop);
            fnNoError = bob.prop.propFunction(true, prop, true);

            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            bob.assert.throwsError(function () { fn(value + ' wrong'); });
            fnNoError(value + ' wrong');
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value += ' Tutisani';
            setter(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //write-only
            value = 'Tengiz';
            prop = new bob.prop.Property(value, false, true);
            var getter = prop.get_getter();
            fn = bob.prop.propFunction(true, prop);
            fnNoError = bob.prop.propFunction(true, prop, true);

            bob.assert.equals(value, getter());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter());

            value += ' Tutisani';
            fn(value);

            bob.assert.equals(value, getter());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter());

        };

        this.test_propFunctionWithCtorParams = function () {

            //read-write
            var value = 20;
            var fn = bob.prop.propFunction(false, value, false, false);
            var fnNoError = bob.prop.propFunction(false, value, false, false, true);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value = 21;
            fn(value);
            fnNoError(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //read-only
            value = 'Tengiz';
            fn = bob.prop.propFunction(false, value, true, false);
            fnNoError = bob.prop.propFunction(false, value, true, false, true);

            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            bob.assert.throwsError(function () { fn(value + ' wrong'); });
            fnNoError(value + ' wrong');
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //write-only
            value = 'Tengiz';
            fn = bob.prop.propFunction(false, value, false, true);
            fnNoError = bob.prop.propFunction(false, value, false, true, true);

            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            
            value += ' Tutisani';
            fn(value);

            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            

        };

        this.test_namedPropFunction = function () {

            //read-write
            var obj = {};
            var value = 20;
            bob.prop.namedPropFunction(obj, 'age', value);
            bob.prop.namedPropFunction(obj, 'ageNoError', value, false, false, true);

            var fn = obj.age;
            var fnNoError = obj.ageNoError
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value = 21;
            fn(value);
            fnNoError(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //read-only
            var obj = {};
            value = 'Tengiz';
            var setter1 = bob.prop.namedPropFunction(obj, 'name', value, true);
            var setter2 = bob.prop.namedPropFunction(obj, 'nameNoError', value, true, false, true);
            fn = obj.name;
            fnNoError = obj.nameNoError;

            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            bob.assert.throwsError(function () { fn(value + ' wrong'); });
            fnNoError(value + ' wrong');
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value += ' Tutisani';
            setter1(value);
            setter2(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //write-only
            var obj = {};
            value = 'Tengiz';
            var getter1 = bob.prop.namedPropFunction(obj, 'name', value, false, true);
            var getter2 = bob.prop.namedPropFunction(obj, 'nameNoError', value, false, true, true);
            fn = obj.name;
            fnNoError = obj.nameNoError;

            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());

            value += ' Tutisani';
            fn(value);
            fnNoError(value);

            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());

        };

        this.test_namedPropFunctionWithPropObj = function () {

            //read-write
            var obj = {};
            var value = 20;
            var propObj = new bob.prop.Property(value);
            bob.prop.namedPropFunction(true, obj, 'age', propObj);
            var propObj = new bob.prop.Property(value);
            bob.prop.namedPropFunction(true, obj, 'ageNoError', propObj, true);

            var fn = obj.age;
            var fnNoError = obj.ageNoError
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value = 21;
            fn(value);
            fnNoError(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //read-only
            var obj = {};
            value = 'Tengiz';
            var propObj = new bob.prop.Property(value, true);
            var setter1 = bob.prop.namedPropFunction(true, obj, 'name', propObj);
            var propObj = new bob.prop.Property(value, true);
            var setter2 = bob.prop.namedPropFunction(true, obj, 'nameNoError', propObj, true);
            fn = obj.name;
            fnNoError = obj.nameNoError;

            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            bob.assert.throwsError(function () { fn(value + ' wrong'); });
            fnNoError(value + ' wrong');
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            value += ' Tutisani';
            setter1(value);
            setter2(value);
            bob.assert.equals(value, fn());
            bob.assert.equals(value, fnNoError());

            //write-only
            var obj = {};
            value = 'Tengiz';
            var propObj = new bob.prop.Property(value, false, true);
            var getter1 = bob.prop.namedPropFunction(true, obj, 'name', propObj);
            var propObj = new bob.prop.Property(value, false, true);
            var getter2 = bob.prop.namedPropFunction(true, obj, 'nameNoError', propObj, true);
            fn = obj.name;
            fnNoError = obj.nameNoError;

            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());

            value += ' Tutisani';
            fn(value);
            fnNoError(value);

            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());
            bob.assert.throwsError(function () { fn(); });
            bob.assert.isUndefined(fnNoError());
            bob.assert.equals(value, getter1());
            bob.assert.equals(value, getter2());

        };
    }

});